home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Controls / Visual Basic Controls.iso / vbcontrol / imgdllll / imgdlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-16  |  38.2 KB  |  1,623 lines

  1. ////////////////////////////////////////////////////////////
  2. //
  3. //    ImgDemo  ImgDLL sample app
  4. //
  5. //    Copyright 1997, smaller animals software
  6. //
  7. //    Author                                     
  8. //    chris losinger,    chrisdl@pagesz.net
  9. //
  10.  
  11. // imgDlg.cpp : implementation file
  12. //
  13.  
  14. #include "stdafx.h"
  15. #include "imgdemo.h"
  16. #include "imgDlg.h"
  17. #include "imgdll.h"
  18.  
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif                                                               
  24.  
  25. // this is the function the DLL will call on every scan line read or written to/from a file
  26. // if it returns a FALSE, the operation aborts
  27. BOOL CALLBACK callBackFn(UINT row, UINT total);
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CAboutDlg dialog used for App About
  31.  
  32. class CAboutDlg : public CDialog
  33. {
  34. public:
  35.     CAboutDlg();
  36.  
  37. // Dialog Data
  38.     //{{AFX_DATA(CAboutDlg)
  39.     enum { IDD = IDD_ABOUTBOX };
  40.     CStatic    m_imgDLLVers;
  41.     //}}AFX_DATA
  42.  
  43.     // ClassWizard generated virtual function overrides
  44.     //{{AFX_VIRTUAL(CAboutDlg)
  45.     protected:
  46.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  47.     //}}AFX_VIRTUAL
  48.  
  49. // Implementation
  50. protected:
  51.     //{{AFX_MSG(CAboutDlg)
  52.     virtual BOOL OnInitDialog();
  53.     //}}AFX_MSG
  54.     DECLARE_MESSAGE_MAP()
  55. };
  56.  
  57. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  58. {
  59.     //{{AFX_DATA_INIT(CAboutDlg)
  60.     //}}AFX_DATA_INIT
  61. }
  62.  
  63. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  64. {
  65.     CDialog::DoDataExchange(pDX);
  66.     //{{AFX_DATA_MAP(CAboutDlg)
  67.     DDX_Control(pDX, IDC_IMGDLLVERS, m_imgDLLVers);
  68.     //}}AFX_DATA_MAP
  69. }
  70.  
  71. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  72.     //{{AFX_MSG_MAP(CAboutDlg)
  73.     //}}AFX_MSG_MAP
  74. END_MESSAGE_MAP()
  75.  
  76. BOOL CAboutDlg::OnInitDialog() 
  77. {
  78.     CDialog::OnInitDialog();
  79.     
  80.     char buf[20];
  81.     ImgDLLGetVersion(buf,20);
  82.  
  83.     CString t;
  84.     t.Format("ImgDLL Version %s", buf);
  85.  
  86.     m_imgDLLVers.SetWindowText(t);
  87.     
  88.     return TRUE;  // return TRUE unless you set the focus to a control
  89.                   // EXCEPTION: OCX Property Pages should return FALSE
  90. }
  91.  
  92. /////////////////////////////////////////////////////////////////////////////
  93. // CImgDlg dialog
  94.  
  95. CImgDlg::CImgDlg(CWnd* pParent /*=NULL*/)
  96.     : CDialog(CImgDlg::IDD, pParent)
  97. {
  98.     //{{AFX_DATA_INIT(CImgDlg)
  99.     //}}AFX_DATA_INIT
  100.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  101.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  102.  
  103.     m_doGray = FALSE;
  104.     m_doRGBBGR= FALSE;
  105.     m_doFlip = FALSE;
  106.     m_doHFlip = FALSE;
  107.     m_doLUT = FALSE;
  108.     m_doMatrix = FALSE;
  109.     m_doSharpen = FALSE;
  110.     m_doBlur = FALSE;
  111.     m_doQuantize = FALSE;
  112.     m_doEQ=FALSE;
  113.  
  114.     //EQ
  115.     m_iEQLowLevel=00;
  116.     m_iEQHighLevel=200;
  117.     m_EQChannelMask=CHRED | CHBLUE | CHGREEN;
  118.  
  119.     // sharpen
  120.     m_iSharpenLevel=25;
  121.  
  122.     // blur
  123.     m_iBlurLevel=50;
  124.  
  125.     // LUT
  126.     for (int lb=0;lb<256;lb++)
  127.         m_LUT[lb]=lb;
  128.  
  129.     m_LUTChannelMask=CHRED | CHBLUE | CHGREEN;
  130.     m_linLut=TRUE;
  131.  
  132.     // matrix - default to a slight embossing effect
  133.     for (int mm=0;mm<9;mm++)
  134.         m_fMatrix[mm]=0.0;
  135.     m_fMatrix[0]=1.0;
  136.     m_fMatrix[4]=1.0;
  137.     m_fMatrix[8]=-1.0;
  138.  
  139.     m_bZero = FALSE;
  140.     m_bFeedback = FALSE;
  141.     m_MatrixChannelMask = CHRED | CHBLUE | CHGREEN;
  142.     m_fMatrixLevel=1.0;
  143.  
  144.     // quantization
  145.     m_iQuantColors = 16;
  146.  
  147.     // global image
  148.     m_rgbBuf=NULL;
  149.     m_width=0;
  150.     m_height=0;
  151.  
  152.     // rotate
  153.     m_quickRotationType = -1;
  154.  
  155.     m_EQGraphMask = 0;    // lum
  156.     for (int i=0; i<256; i++) m_EQHisto[i]=0;
  157.  
  158.     MakePalette();
  159. }
  160.  
  161. CImgDlg::~CImgDlg()
  162. {
  163.     CleanUp();
  164.     m_pal.DeleteObject();
  165. }
  166.  
  167. //
  168. //    make sure all the controls have the values we want them to have
  169. //
  170.  
  171. void CImgDlg::SetAllControls()
  172. {
  173.     CString txt;
  174.     // sharpen
  175.     txt.Format("%d", m_iSharpenLevel);
  176.     m_sharpenLevelWnd.SetWindowText(txt);
  177.     m_sharpenCheck.SetCheck(m_doSharpen);
  178.  
  179.     // blur
  180.     txt.Format("%d", m_iBlurLevel);
  181.     m_BlurLevelWnd.SetWindowText(txt);
  182.     m_BlurCheck.SetCheck(m_doBlur);
  183.  
  184.     // matrix
  185.     txt.Format("%6.4f", m_fMatrix[8]);
  186.     m_matrix8Wnd.SetWindowText(txt);
  187.     txt.Format("%6.4f", m_fMatrix[7]);
  188.     m_matrix7Wnd.SetWindowText(txt);
  189.     txt.Format("%6.4f", m_fMatrix[6]);
  190.     m_matrix6Wnd.SetWindowText(txt);
  191.     txt.Format("%6.4f", m_fMatrix[5]);
  192.     m_matrix5Wnd.SetWindowText(txt);
  193.     txt.Format("%6.4f", m_fMatrix[4]);
  194.     m_matrix4Wnd.SetWindowText(txt);
  195.     txt.Format("%6.4f", m_fMatrix[3]);
  196.     m_matrix3Wnd.SetWindowText(txt);
  197.     txt.Format("%6.4f", m_fMatrix[2]);
  198.     m_matrix2Wnd.SetWindowText(txt);
  199.     txt.Format("%6.4f", m_fMatrix[1]);
  200.     m_matrix1Wnd.SetWindowText(txt);
  201.     txt.Format("%6.4f", m_fMatrix[0]);
  202.     m_matrix0Wnd.SetWindowText(txt);
  203.  
  204.     m_matrixZeroCheck.SetCheck(m_bZero);
  205.     m_matrixRedCheck.SetCheck(((m_MatrixChannelMask & CHRED) == CHRED));
  206.     m_matrixGreenCheck.SetCheck(((m_MatrixChannelMask & CHGREEN) == CHGREEN));
  207.     m_matrixBlueCheck.SetCheck(((m_MatrixChannelMask & CHBLUE) == CHBLUE));
  208.     m_matrixOnCheck.SetCheck(m_doMatrix);
  209.     m_matrixFeedbackCheck.SetCheck(m_bFeedback);
  210.  
  211.     txt.Format("%6.4f", m_fMatrixLevel);
  212.     m_matrixLevelWnd.SetWindowText(txt);
  213.  
  214.     // lut
  215.     m_LUTRedCheck.SetCheck(((m_LUTChannelMask & CHRED) == CHRED));
  216.     m_LUTGreenCheck.SetCheck(((m_LUTChannelMask & CHGREEN) == CHGREEN));
  217.     m_LUTBlueCheck.SetCheck(((m_LUTChannelMask & CHBLUE) == CHBLUE));
  218.     CheckRadioButton(IDC_LINLUT, IDC_INVLUT, (m_linLut ? IDC_LINLUT : IDC_INVLUT));
  219.  
  220.     // stuff
  221.     m_grayCheck.SetCheck(m_doGray);
  222.     m_rgbbgrCheck.SetCheck(m_doRGBBGR);
  223.     m_flipCheck.SetCheck(m_doFlip);
  224.     m_hFlipCheck.SetCheck(m_doHFlip);
  225.  
  226.     // quant
  227.     m_quantCheck.SetCheck(m_doQuantize);
  228.     txt.Format("%d",m_iQuantColors);
  229.     m_quantColorsWnd.SetWindowText(txt);
  230.  
  231.     // eq
  232.     m_histRedCheck.SetCheck(((m_EQChannelMask & CHRED) == CHRED));
  233.     m_histGreenCheck.SetCheck(((m_EQChannelMask & CHGREEN) == CHGREEN));
  234.     m_histBlueCheck.SetCheck(((m_EQChannelMask & CHBLUE) == CHBLUE));
  235.     m_histCheck.SetCheck(m_doEQ);
  236.     txt.Format("%d",m_iEQLowLevel);
  237.     m_histLowWnd.SetWindowText(txt);
  238.     txt.Format("%d",m_iEQHighLevel);
  239.     m_histHighWnd.SetWindowText(txt);
  240.  
  241.     // quick rotate
  242.     CheckRadioButton(IDC_ROTATE_NONE, IDC_ROTATE_270, IDC_ROTATE_NONE);
  243.  
  244.  
  245.     CheckRadioButton(IDC_EQ_LUM, IDC_EQ_BLUE, IDC_EQ_LUM);
  246. }
  247.  
  248. void CImgDlg::DoDataExchange(CDataExchange* pDX)
  249. {
  250.     CDialog::DoDataExchange(pDX);
  251.     //{{AFX_DATA_MAP(CImgDlg)
  252.     DDX_Control(pDX, IDC_HISTO_FRAME, m_histoFrame);
  253.     DDX_Control(pDX, IDC_COLOR_TEXT, m_colorTextWnd);
  254.     DDX_Control(pDX, IDC_HORIZFLIP, m_hFlipCheck);
  255.     DDX_Control(pDX, IDC_HIST_GREEN, m_histGreenCheck);
  256.     DDX_Control(pDX, IDC_HISTCHECK, m_histCheck);
  257.     DDX_Control(pDX, IDC_HIST_RED, m_histRedCheck);
  258.     DDX_Control(pDX, IDC_HIST_LOW, m_histLowWnd);
  259.     DDX_Control(pDX, IDC_HIST_HIGH, m_histHighWnd);
  260.     DDX_Control(pDX, IDC_HIST_BLUE, m_histBlueCheck);
  261.     DDX_Control(pDX, IDC_IMGRECT_BEFORE, m_beforeRectWnd);
  262.     DDX_Control(pDX, IDC_QUANT_COLORS, m_quantColorsWnd);
  263.     DDX_Control(pDX, IDC_QUANTIZE_CHECK, m_quantCheck);
  264.     DDX_Control(pDX, IDC_LUTCHECK, m_LUTCheck);
  265.     DDX_Control(pDX, IDC_RGBBGR, m_rgbbgrCheck);
  266.     DDX_Control(pDX, IDC_GRAYSCALE, m_grayCheck);
  267.     DDX_Control(pDX, IDC_FLIP, m_flipCheck);
  268.     DDX_Control(pDX, IDC_IMGRECT, m_imgRectWnd);
  269.     DDX_Control(pDX, IDC_SHARPEN_LEVEL, m_sharpenLevelWnd);
  270.     DDX_Control(pDX, IDC_SHARPEN_CHECK, m_sharpenCheck);
  271.     DDX_Control(pDX, IDC_MATRIX8, m_matrix8Wnd);
  272.     DDX_Control(pDX, IDC_MATRIX7, m_matrix7Wnd);
  273.     DDX_Control(pDX, IDC_MATRIX6, m_matrix6Wnd);
  274.     DDX_Control(pDX, IDC_MATRIX5, m_matrix5Wnd);
  275.     DDX_Control(pDX, IDC_MATRIX4, m_matrix4Wnd);
  276.     DDX_Control(pDX, IDC_MATRIX3, m_matrix3Wnd);
  277.     DDX_Control(pDX, IDC_MATRIX2, m_matrix2Wnd);
  278.     DDX_Control(pDX, IDC_MATRIX0, m_matrix0Wnd);
  279.     DDX_Control(pDX, IDC_MATRIX1, m_matrix1Wnd);
  280.     DDX_Control(pDX, IDC_MATRIX_ZERO, m_matrixZeroCheck);
  281.     DDX_Control(pDX, IDC_MATRIX_RED, m_matrixRedCheck);
  282.     DDX_Control(pDX, IDC_MATRIX_ON, m_matrixOnCheck);
  283.     DDX_Control(pDX, IDC_MATRIX_LEVEL, m_matrixLevelWnd);
  284.     DDX_Control(pDX, IDC_MATRIX_GREEN, m_matrixGreenCheck);
  285.     DDX_Control(pDX, IDC_MATRIX_FEEDBACK, m_matrixFeedbackCheck);
  286.     DDX_Control(pDX, IDC_MATRIX_BLUE, m_matrixBlueCheck);
  287.     DDX_Control(pDX, IDC_LUT_RED, m_LUTRedCheck);
  288.     DDX_Control(pDX, IDC_LUT_GREEN, m_LUTGreenCheck);
  289.     DDX_Control(pDX, IDC_LUT_BLUE, m_LUTBlueCheck);
  290.     DDX_Control(pDX, IDC_BLUR_LEVEL, m_BlurLevelWnd);
  291.     DDX_Control(pDX, IDC_BLUR_CHECK, m_BlurCheck);
  292.     //}}AFX_DATA_MAP
  293. }
  294.  
  295. BEGIN_MESSAGE_MAP(CImgDlg, CDialog)
  296.     //{{AFX_MSG_MAP(CImgDlg)
  297.     ON_WM_SYSCOMMAND()
  298.     ON_WM_PAINT()
  299.     ON_WM_QUERYDRAGICON()
  300.     ON_BN_CLICKED(IDC_BLUR_CHECK, OnBlurCheck)
  301.     ON_EN_CHANGE(IDC_BLUR_LEVEL, OnChangeBlurLevel)
  302.     ON_BN_CLICKED(IDC_FLIP, OnFlip)
  303.     ON_BN_CLICKED(IDC_GRAYSCALE, OnGrayscale)
  304.     ON_BN_CLICKED(IDC_LUT_BLUE, OnLutBlue)
  305.     ON_BN_CLICKED(IDC_LUT_GREEN, OnLutGreen)
  306.     ON_BN_CLICKED(IDC_LUT_RED, OnLutRed)
  307.     ON_BN_CLICKED(IDC_MATRIX_BLUE, OnMatrixBlue)
  308.     ON_BN_CLICKED(IDC_MATRIX_FEEDBACK, OnMatrixFeedback)
  309.     ON_BN_CLICKED(IDC_MATRIX_GREEN, OnMatrixGreen)
  310.     ON_EN_CHANGE(IDC_MATRIX_LEVEL, OnChangeMatrixLevel)
  311.     ON_BN_CLICKED(IDC_MATRIX_ON, OnMatrixOn)
  312.     ON_BN_CLICKED(IDC_MATRIX_RED, OnMatrixRed)
  313.     ON_BN_CLICKED(IDC_MATRIX_ZERO, OnMatrixZero)
  314.     ON_EN_CHANGE(IDC_MATRIX0, OnChangeMatrix0)
  315.     ON_EN_CHANGE(IDC_MATRIX1, OnChangeMatrix1)
  316.     ON_EN_CHANGE(IDC_MATRIX2, OnChangeMatrix2)
  317.     ON_EN_CHANGE(IDC_MATRIX3, OnChangeMatrix3)
  318.     ON_EN_CHANGE(IDC_MATRIX4, OnChangeMatrix4)
  319.     ON_EN_CHANGE(IDC_MATRIX5, OnChangeMatrix5)
  320.     ON_EN_CHANGE(IDC_MATRIX6, OnChangeMatrix6)
  321.     ON_EN_CHANGE(IDC_MATRIX7, OnChangeMatrix7)
  322.     ON_EN_CHANGE(IDC_MATRIX8, OnChangeMatrix8)
  323.     ON_BN_CLICKED(IDC_OPEN, OnOpen)
  324.     ON_BN_CLICKED(IDC_RGBBGR, OnRgbbgr)
  325.     ON_BN_CLICKED(IDC_SAVE, OnSave)
  326.     ON_BN_CLICKED(IDC_SHARPEN_CHECK, OnSharpenCheck)
  327.     ON_EN_CHANGE(IDC_SHARPEN_LEVEL, OnChangeSharpenLevel)
  328.     ON_BN_CLICKED(IDC_INVLUT, OnInvlut)
  329.     ON_BN_CLICKED(IDC_LINLUT, OnLinlut)
  330.     ON_BN_CLICKED(IDC_LUTCHECK, OnLutcheck)
  331.     ON_BN_CLICKED(IDC_QUANTIZE_CHECK, OnQuantizeCheck)
  332.     ON_BN_CLICKED(IDC_ABOUT, OnAbout)
  333.     ON_EN_CHANGE(IDC_QUANT_COLORS, OnChangeQuantColors)
  334.     ON_BN_CLICKED(IDC_HIST_BLUE, OnHistBlue)
  335.     ON_BN_CLICKED(IDC_HIST_GREEN, OnHistGreen)
  336.     ON_EN_CHANGE(IDC_HIST_HIGH, OnChangeHistHigh)
  337.     ON_EN_CHANGE(IDC_HIST_LOW, OnChangeHistLow)
  338.     ON_BN_CLICKED(IDC_HIST_RED, OnHistRed)
  339.     ON_BN_CLICKED(IDC_HISTCHECK, OnHistcheck)
  340.     ON_BN_CLICKED(IDC_HORIZFLIP, OnHorizflip)
  341.     ON_BN_CLICKED(IDC_ROTATE_180, OnRotate180)
  342.     ON_BN_CLICKED(IDC_ROTATE_270, OnRotate270)
  343.     ON_BN_CLICKED(IDC_ROTATE_90, OnRotate90)
  344.     ON_BN_CLICKED(IDC_ROTATE_NONE, OnRotateNone)
  345.     ON_BN_CLICKED(IDC_EQ_BLUE, OnEqBlue)
  346.     ON_BN_CLICKED(IDC_EQ_GREEN, OnEqGreen)
  347.     ON_BN_CLICKED(IDC_EQ_LUM, OnEqLum)
  348.     ON_BN_CLICKED(IDC_EQ_RED, OnEqRed)
  349.     //}}AFX_MSG_MAP
  350. END_MESSAGE_MAP()
  351.  
  352. /////////////////////////////////////////////////////////////////////////////
  353. // CImgDlg message handlers
  354.  
  355. BOOL CImgDlg::OnInitDialog()
  356. {
  357.     CDialog::OnInitDialog();
  358.  
  359.     // Add "About..." menu item to system menu.
  360.  
  361.     // IDM_ABOUTBOX must be in the system command range.
  362.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  363.     ASSERT(IDM_ABOUTBOX < 0xF000);
  364.  
  365.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  366.     if (pSysMenu != NULL)
  367.     {
  368.         CString strAboutMenu;
  369.         strAboutMenu.LoadString(IDS_ABOUTBOX);
  370.         if (!strAboutMenu.IsEmpty())
  371.         {
  372.             pSysMenu->AppendMenu(MF_SEPARATOR);
  373.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  374.         }
  375.     }
  376.  
  377.     // Set the icon for this dialog.  The framework does this automatically
  378.     //  when the application's main window is not a dialog
  379.     SetIcon(m_hIcon, TRUE);            // Set big icon
  380.     SetIcon(m_hIcon, FALSE);        // Set small icon
  381.     
  382.     // TODO: Add extra initialization here
  383.     SetAllControls();
  384.  
  385.     // tell the DLL that we're going to use it
  386.     ImgDLLInitDLL(IMGDLL_LOCK_KEY);
  387.  
  388.     // tell the DLL to call the function "callBackFn" on every scan line
  389.     // read or written
  390.     ImgDLLSetCallback(callBackFn);
  391.  
  392.     // load the sample image
  393.     LoadDefaultImage();
  394.  
  395.     return TRUE;  // return TRUE  unless you set the focus to a control
  396. }
  397.  
  398. void CImgDlg::OnSysCommand(UINT nID, LPARAM lParam)
  399. {
  400.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  401.     {
  402.         CAboutDlg dlgAbout;
  403.         dlgAbout.DoModal();
  404.     }
  405.     else
  406.     {
  407.         CDialog::OnSysCommand(nID, lParam);
  408.     }
  409. }
  410.  
  411. // If you add a minimize button to your dialog, you will need the code below
  412. //  to draw the icon.  For MFC applications using the document/view model,
  413. //  this is automatically done for you by the framework.
  414.  
  415. void CImgDlg::OnPaint() 
  416. {
  417.     if (IsIconic())
  418.     {
  419.         CPaintDC dc(this); // device context for painting
  420.  
  421.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  422.  
  423.         // Center icon in client rectangle
  424.         int cxIcon = GetSystemMetrics(SM_CXICON);
  425.         int cyIcon = GetSystemMetrics(SM_CYICON);
  426.         CRect rect;
  427.         GetClientRect(&rect);
  428.         int x = (rect.Width() - cxIcon + 1) / 2;
  429.         int y = (rect.Height() - cyIcon + 1) / 2;
  430.  
  431.         // Draw the icon
  432.         dc.DrawIcon(x, y, m_hIcon);
  433.     }
  434.     else
  435.     {
  436.         CPaintDC dc(this); // device context for painting
  437.  
  438.         CPalette * op = dc.SelectPalette(&m_pal,FALSE);
  439.         dc.RealizePalette();
  440.  
  441.         // where to draw to
  442.         CRect afterRect;
  443.         m_imgRectWnd.GetWindowRect(afterRect);
  444.         ScreenToClient(afterRect);
  445.         afterRect.InflateRect(-2,-2);
  446.         dc.FillRect(afterRect, &CBrush(::GetSysColor(COLOR_3DFACE)));
  447.  
  448.         // where to draw to
  449.         CRect beforeRect;
  450.         m_beforeRectWnd.GetWindowRect(beforeRect);
  451.         ScreenToClient(beforeRect);
  452.         beforeRect.InflateRect(-2,-2);
  453.         dc.FillRect(beforeRect, &CBrush(::GetSysColor(COLOR_3DFACE)));
  454.  
  455.         // draw the before image
  456.  
  457.         // this call wraps a call to ImgDLLRGBToHBITMAP as well as all the
  458.         // usual CreateCompatibleDC, SelectObject, BitBlt stuff
  459.         if (m_rgbBuf!=NULL) 
  460.             ImgDLLDrawRGB(dc.m_hDC,
  461.                         m_rgbBuf, 
  462.                         m_width, m_height, 
  463.                         beforeRect.left,
  464.                         beforeRect.top,
  465.                         min(100,m_width),        // clip
  466.                         min(100,m_height),
  467.                         (HPALETTE)m_pal.GetSafeHandle());    //optional
  468.  
  469.  
  470.  
  471.         // apply the changes to generate the "after" image
  472.         BYTE *outputImage = RenderImage();
  473.  
  474.         // draw the After image
  475.         if (outputImage!=NULL) {
  476.  
  477.             ImgDLLDrawRGB(dc.m_hDC,
  478.                         outputImage, 
  479.                         m_width, m_height, 
  480.                         afterRect.left,
  481.                         afterRect.top,
  482.                         min(100,m_width),        // clip
  483.                         min(100,m_height),
  484.                         (HPALETTE)m_pal.GetSafeHandle()); //optional
  485.  
  486.             delete [] outputImage;
  487.         }
  488.  
  489.         // draw histo graph
  490.  
  491.         // where to draw to
  492.         CRect graphRect;
  493.         m_histoFrame.GetWindowRect(graphRect);
  494.         ScreenToClient(graphRect);
  495.         graphRect.InflateRect(-2,-2);
  496.         dc.FillRect(graphRect, CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH)));
  497.  
  498.         int maxval = 0;
  499.         for (int z = 0; z<256; z++)
  500.             maxval = max(maxval, m_EQHisto[z]);
  501.         if (maxval > 0) {
  502.             double xscale = (double)(graphRect.Width() - 5) / 256;
  503.             double yscale = (double)(graphRect.Height() - 5) / maxval;
  504.             for (int i=0; i<255; i++) {
  505.                 double xpos = xscale * i + 2 + graphRect.left;
  506.                 double ypos = graphRect.bottom - (yscale * m_EQHisto[i] + 2);
  507.  
  508.                 dc.MoveTo((int)xpos, (int)ypos);
  509.                 dc.LineTo((int)xpos, (graphRect.bottom - 2));
  510.  
  511.             }
  512.         }
  513.  
  514.         dc.SelectPalette(op, FALSE);
  515.  
  516.         CDialog::OnPaint();
  517.     }
  518. }
  519.  
  520. // The system calls this to obtain the cursor to display while the user drags
  521. //  the minimized window.
  522. HCURSOR CImgDlg::OnQueryDragIcon()
  523. {
  524.     return (HCURSOR) m_hIcon;
  525. }
  526.  
  527. // call this when we want to redraw the After image
  528. void CImgDlg::InvalidateAfterImage()
  529. {
  530.     // where to draw to
  531.     CRect outRect;
  532.     m_imgRectWnd.GetWindowRect(outRect);
  533.     ScreenToClient(outRect);
  534.  
  535.     InvalidateRect(outRect, FALSE);
  536.  
  537.     CRect graphRect;
  538.     m_histoFrame.GetWindowRect(graphRect);
  539.     ScreenToClient(graphRect);
  540.  
  541.     InvalidateRect(graphRect, FALSE);
  542.  
  543. }
  544.  
  545. // call this when we want to redraw the Before image
  546. void CImgDlg::InvalidateBeforeImage()
  547. {
  548.     // where to draw to
  549.     CRect outRect;
  550.     m_beforeRectWnd.GetWindowRect(outRect);
  551.     ScreenToClient(outRect);
  552.  
  553.     InvalidateRect(outRect, FALSE);
  554. }
  555.  
  556. ////////////////////////////////////////////////////////////////////////
  557. // a thousand control handlers....
  558.  
  559. void CImgDlg::OnBlurCheck() 
  560. {
  561.     m_doBlur = m_BlurCheck.GetCheck();
  562.     InvalidateAfterImage();
  563. }
  564.  
  565. void CImgDlg::OnChangeBlurLevel() 
  566. {
  567.     CString txt;
  568.     m_BlurLevelWnd.GetWindowText(txt);
  569.     m_iBlurLevel=atoi(txt);
  570.  
  571.     InvalidateAfterImage();
  572. }
  573.  
  574. ////////////////////////////////////////////////////////////////////////
  575.  
  576. void CImgDlg::OnSharpenCheck() 
  577. {
  578.     m_doSharpen = m_sharpenCheck.GetCheck();
  579.     InvalidateAfterImage();
  580. }
  581.  
  582. void CImgDlg::OnChangeSharpenLevel() 
  583. {
  584.     CString txt;
  585.     m_sharpenLevelWnd.GetWindowText(txt);
  586.     m_iSharpenLevel=atoi(txt);
  587.  
  588.     InvalidateAfterImage();
  589. }
  590.  
  591. ////////////////////////////////////////////////////////////////////////
  592.  
  593. void CImgDlg::OnFlip() 
  594. {
  595.     m_doFlip = m_flipCheck.GetCheck();
  596.     InvalidateAfterImage();
  597. }
  598.  
  599. ////////////////////////////////////////////////////////////////////////
  600.  
  601. void CImgDlg::OnHorizflip() 
  602. {
  603.     m_doHFlip = m_hFlipCheck.GetCheck();
  604.     InvalidateAfterImage();
  605. }
  606.  
  607. ////////////////////////////////////////////////////////////////////////
  608.  
  609. void CImgDlg::OnRgbbgr() 
  610. {
  611.     m_doRGBBGR = m_rgbbgrCheck.GetCheck();
  612.     InvalidateAfterImage();
  613. }
  614.  
  615. ////////////////////////////////////////////////////////////////////////
  616.  
  617. void CImgDlg::OnGrayscale() 
  618. {
  619.     m_doGray = m_grayCheck.GetCheck();
  620.     InvalidateAfterImage();
  621. }
  622.  
  623.  
  624. ////////////////////////////////////////////////////////////////////////
  625.  
  626. void CImgDlg::OnLutcheck() 
  627. {
  628.     m_doLUT = m_LUTCheck.GetCheck();
  629.     InvalidateAfterImage();
  630. }
  631.  
  632. void CImgDlg::OnLutBlue() 
  633. {
  634.     BOOL check = m_LUTBlueCheck.GetCheck();
  635.     if (check)
  636.         m_LUTChannelMask = m_LUTChannelMask | CHBLUE;
  637.     else 
  638.         m_LUTChannelMask = m_LUTChannelMask ^ CHBLUE;
  639.  
  640.     InvalidateAfterImage();
  641. }
  642.  
  643. void CImgDlg::OnLutGreen() 
  644. {
  645.     BOOL check = m_LUTGreenCheck.GetCheck();
  646.     if (check)
  647.         m_LUTChannelMask = m_LUTChannelMask | CHGREEN;
  648.     else 
  649.         m_LUTChannelMask = m_LUTChannelMask ^ CHGREEN;
  650.  
  651.     InvalidateAfterImage();
  652. }
  653.  
  654. void CImgDlg::OnLutRed() 
  655. {
  656.     BOOL check = m_LUTRedCheck.GetCheck();
  657.     if (check)
  658.         m_LUTChannelMask = m_LUTChannelMask | CHRED;
  659.     else 
  660.         m_LUTChannelMask = m_LUTChannelMask ^ CHRED;
  661.  
  662.     InvalidateAfterImage();
  663. }
  664.  
  665.  
  666. void CImgDlg::OnInvlut() 
  667. {
  668.     CButton * pBut = (CButton *)GetDlgItem(IDC_INVLUT);
  669.     m_linLut=!(pBut->GetCheck());
  670.     SetLUT();
  671.     InvalidateAfterImage();
  672. }
  673.  
  674. void CImgDlg::OnLinlut() 
  675. {
  676.     CButton * pBut = (CButton *)GetDlgItem(IDC_LINLUT);
  677.     m_linLut=(pBut->GetCheck());
  678.     SetLUT();
  679.     InvalidateAfterImage();
  680. }
  681.  
  682. void CImgDlg::SetLUT()
  683. {
  684.     for (int i=0;i<256;i++) {
  685.         m_LUT[i] = (m_linLut ? i : 256 - i);
  686.     }
  687. }
  688.  
  689. ////////////////////////////////////////////////////////////////////////
  690.  
  691. void CImgDlg::OnHistRed() 
  692. {
  693.     BOOL check = m_histRedCheck.GetCheck();
  694.     if (check)
  695.         m_EQChannelMask = m_EQChannelMask  | CHRED;
  696.     else 
  697.         m_EQChannelMask  = m_EQChannelMask  ^ CHRED;
  698.  
  699.     InvalidateAfterImage();
  700. }
  701.  
  702. void CImgDlg::OnHistBlue() 
  703. {
  704.     BOOL check = m_histBlueCheck.GetCheck();
  705.     if (check)
  706.         m_EQChannelMask = m_EQChannelMask  | CHBLUE;
  707.     else 
  708.         m_EQChannelMask  = m_EQChannelMask  ^ CHBLUE;
  709.  
  710.     InvalidateAfterImage();
  711. }
  712.  
  713. void CImgDlg::OnHistGreen() 
  714. {
  715.     BOOL check = m_histGreenCheck.GetCheck();
  716.     if (check)
  717.         m_EQChannelMask = m_EQChannelMask  | CHGREEN;
  718.     else 
  719.         m_EQChannelMask  = m_EQChannelMask  ^ CHGREEN;
  720.  
  721.     InvalidateAfterImage();    
  722. }
  723.  
  724. void CImgDlg::OnChangeHistHigh() 
  725. {
  726.     CString txt;
  727.     m_histHighWnd.GetWindowText(txt);
  728.     m_iEQHighLevel=atoi(txt);
  729.  
  730.     InvalidateAfterImage();
  731. }
  732.  
  733. void CImgDlg::OnChangeHistLow() 
  734. {
  735.     CString txt;
  736.     m_histLowWnd.GetWindowText(txt);
  737.     m_iEQLowLevel=atoi(txt);
  738.  
  739.     InvalidateAfterImage();
  740. }
  741.  
  742. void CImgDlg::OnHistcheck() 
  743. {
  744.     m_doEQ = m_histCheck.GetCheck();
  745.     InvalidateAfterImage();
  746. }
  747.  
  748.  
  749. ////////////////////////////////////////////////////////////////////////
  750.  
  751. void CImgDlg::OnRotate180() 
  752. {
  753.     m_quickRotationType = 1;
  754.     InvalidateAfterImage();
  755. }
  756.  
  757. void CImgDlg::OnRotate270() 
  758. {
  759.     m_quickRotationType = 2;
  760.     InvalidateAfterImage();
  761. }
  762.  
  763. void CImgDlg::OnRotate90() 
  764. {
  765.     m_quickRotationType = 0;
  766.     InvalidateAfterImage();
  767. }
  768.  
  769. void CImgDlg::OnRotateNone() 
  770. {
  771.     m_quickRotationType = -1;
  772.     InvalidateAfterImage();
  773. }
  774.  
  775. ////////////////////////////////////////////////////////////////////////
  776.  
  777. void CImgDlg::OnMatrixOn() 
  778. {
  779.     m_doMatrix = m_matrixOnCheck.GetCheck();
  780.     InvalidateAfterImage();
  781. }
  782.  
  783. void CImgDlg::OnMatrixZero() 
  784. {
  785.     m_bZero = m_matrixZeroCheck.GetCheck();
  786.     InvalidateAfterImage();
  787. }
  788.  
  789.  
  790. void CImgDlg::OnMatrixBlue() 
  791. {
  792.     BOOL check = m_matrixBlueCheck.GetCheck();
  793.     if (check)
  794.         m_MatrixChannelMask = m_MatrixChannelMask  | CHBLUE;
  795.     else 
  796.         m_MatrixChannelMask  = m_MatrixChannelMask  ^ CHBLUE;
  797.  
  798.     InvalidateAfterImage();
  799. }
  800.  
  801. void CImgDlg::OnMatrixRed() 
  802. {
  803.     BOOL check = m_matrixRedCheck.GetCheck();
  804.     if (check)
  805.         m_MatrixChannelMask = m_MatrixChannelMask  | CHRED;
  806.     else 
  807.         m_MatrixChannelMask  = m_MatrixChannelMask  ^ CHRED;
  808.  
  809.     InvalidateAfterImage();
  810. }
  811.  
  812. void CImgDlg::OnMatrixGreen() 
  813. {
  814.     BOOL check = m_matrixGreenCheck.GetCheck();
  815.     if (check)
  816.         m_MatrixChannelMask = m_MatrixChannelMask  | CHGREEN;
  817.     else 
  818.         m_MatrixChannelMask  = m_MatrixChannelMask  ^ CHGREEN;
  819.  
  820.     InvalidateAfterImage();
  821. }
  822.  
  823. void CImgDlg::OnMatrixFeedback() 
  824. {
  825.     m_bFeedback =  m_matrixFeedbackCheck.GetCheck();
  826.     InvalidateAfterImage();
  827. }
  828.  
  829. void CImgDlg::OnChangeMatrixLevel() 
  830. {
  831.     CString txt;
  832.     m_matrixLevelWnd.GetWindowText(txt);
  833.     m_fMatrixLevel=atof(txt);
  834.     
  835.     InvalidateAfterImage();
  836. }
  837.  
  838. void CImgDlg::OnChangeMatrix0() 
  839. {
  840.     CString txt;
  841.     m_matrix0Wnd.GetWindowText(txt);
  842.     m_fMatrix[0]=atof(txt);
  843.  
  844.     InvalidateAfterImage();
  845. }
  846.  
  847. void CImgDlg::OnChangeMatrix1() 
  848. {
  849.     CString txt;
  850.     m_matrix1Wnd.GetWindowText(txt);
  851.     m_fMatrix[1]=atof(txt);
  852.  
  853.     InvalidateAfterImage();
  854. }
  855.  
  856. void CImgDlg::OnChangeMatrix2() 
  857. {
  858.     CString txt;
  859.     m_matrix2Wnd.GetWindowText(txt);
  860.     m_fMatrix[2]=atof(txt);
  861.  
  862.     InvalidateAfterImage();
  863. }
  864.  
  865. void CImgDlg::OnChangeMatrix3() 
  866. {
  867.     CString txt;
  868.     m_matrix3Wnd.GetWindowText(txt);
  869.     m_fMatrix[3]=atof(txt);
  870.  
  871.     InvalidateAfterImage();
  872. }
  873.  
  874. void CImgDlg::OnChangeMatrix4() 
  875. {
  876.     CString txt;
  877.     m_matrix4Wnd.GetWindowText(txt);
  878.     m_fMatrix[4]=atof(txt);
  879.  
  880.     InvalidateAfterImage();
  881. }
  882.  
  883. void CImgDlg::OnChangeMatrix5() 
  884. {
  885.     CString txt;
  886.     m_matrix5Wnd.GetWindowText(txt);
  887.     m_fMatrix[5]=atof(txt);
  888.  
  889.     InvalidateAfterImage();
  890. }
  891.  
  892. void CImgDlg::OnChangeMatrix6() 
  893. {
  894.     CString txt;
  895.     m_matrix6Wnd.GetWindowText(txt);
  896.     m_fMatrix[6]=atof(txt);
  897.  
  898.     InvalidateAfterImage();
  899. }
  900.  
  901. void CImgDlg::OnChangeMatrix7() 
  902. {
  903.     CString txt;
  904.     m_matrix7Wnd.GetWindowText(txt);
  905.     m_fMatrix[7]=atof(txt);
  906.  
  907.     InvalidateAfterImage();
  908. }
  909.  
  910. void CImgDlg::OnChangeMatrix8() 
  911. {
  912.     CString txt;
  913.     m_matrix8Wnd.GetWindowText(txt);
  914.     m_fMatrix[8]=atof(txt);
  915.  
  916.     InvalidateAfterImage();
  917. }
  918.  
  919. ////////////////////////////////////////////////////////////////////////
  920.  
  921.  
  922.  
  923. void CImgDlg::OnEqBlue() 
  924. {
  925.     m_EQGraphMask = CHBLUE;
  926.     InvalidateAfterImage();
  927. }
  928.  
  929. void CImgDlg::OnEqGreen() 
  930. {
  931.     m_EQGraphMask = CHGREEN;
  932.     InvalidateAfterImage();
  933. }
  934.  
  935. void CImgDlg::OnEqLum() 
  936. {
  937.     m_EQGraphMask = 0;
  938.     InvalidateAfterImage();
  939. }
  940.  
  941. void CImgDlg::OnEqRed() 
  942. {
  943.     m_EQGraphMask = CHRED;
  944.     InvalidateAfterImage();
  945. }
  946.  
  947. ////////////////////////////////////////////////////////////////////////
  948.  
  949. void CImgDlg::OnQuantizeCheck() 
  950. {
  951.     m_doQuantize=m_quantCheck.GetCheck();    
  952.     InvalidateAfterImage();
  953. }
  954.  
  955.  
  956.  
  957. void CImgDlg::OnChangeQuantColors() 
  958. {
  959.     CString txt;
  960.     m_quantColorsWnd.GetWindowText(txt);
  961.     m_iQuantColors=atoi(txt);
  962.  
  963.     InvalidateAfterImage();
  964. }
  965.  
  966.  
  967. // the ImgDLL DLL will call this function once for every scan line
  968. // read or written to a JPG, PNG or BMP file. if this function returns FALSE
  969. // the operation aborts and ImgDLLGetLastError will return CALLBACKCANCEL
  970. //
  971. //    you can use this to monitor the progress of read / write operations
  972. BOOL CALLBACK callBackFn(UINT row, UINT total) 
  973. {
  974.     double perc;
  975.     perc = 100 * (double)row / (double)total;
  976.     TRACE3("Callback at row : %u  total : %u  %f percent done\n",row, total, perc);
  977.  
  978.     return TRUE;   // don't abort
  979. }
  980.  
  981. ////////////////////////////////////////////////////////////////////////
  982.  
  983. void CImgDlg::OnOpen() 
  984. {
  985.     CString fileName;
  986.     CString filt="Image Files (jpg,bmp,gif,pcx,png,tiff)|Image Files *.BMP;*.JPG;*.PCX;*.PNG;*.TIF;*.GIF| \
  987. JPG Files (*.JPG)|*.JPG| \
  988. PNG Files (*.PNG)|*.PNG| \
  989. TIFF Files (*.TIF)|*.TIF| \
  990. BMP Files (*.BMP)|*.BMP| \
  991. PCX Files (*.PCX)|*.PCX| \
  992. GIF Files (*.GIF)|*.GIF| \
  993. All files (*.*)|*.*||";
  994.  
  995.     // OPENFILENAME - so i can get to its Help page easily
  996.  
  997.     CString defFilt = "*.BMP;*.JPG;*.PCX;*.PNG;*.TIF;*.GIF";
  998.     CFileDialog fileDlg(TRUE,defFilt, defFilt, NULL,filt,this);
  999.  
  1000.     fileDlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
  1001.     fileDlg.m_ofn.lpstrTitle="File to load";
  1002.  
  1003.     if (fileDlg.DoModal()==IDOK) {
  1004.  
  1005.         AfxGetApp()->DoWaitCursor(1);
  1006.  
  1007.         fileName=fileDlg.GetPathName();
  1008.         CString ext=fileName.Right(4);
  1009.  
  1010.         HGLOBAL hImg=NULL;
  1011.  
  1012.         UINT w,h;
  1013.  
  1014.         // read new image
  1015.         if (!ext.CompareNoCase(".JPG"))
  1016.             hImg = ImgDLLReadRGBFromJPG(fileName, &w, &h);
  1017.  
  1018.         if (!ext.CompareNoCase(".PNG"))
  1019.             hImg = ImgDLLReadRGBFromPNG(fileName, &w, &h);
  1020.  
  1021.         if (!ext.CompareNoCase(".TIF"))
  1022.             hImg = ImgDLLTIFFToRGB(fileName, &w, &h);
  1023.  
  1024.         if (!ext.CompareNoCase(".BMP"))
  1025.             hImg = ImgDLLReadRGBFromBMP(fileName, &w, &h);
  1026.  
  1027.         if (!ext.CompareNoCase(".PCX"))
  1028.             hImg = ImgDLLReadRGBFromPCX(fileName, &w, &h);
  1029.         
  1030.         if (hImg!=NULL) {
  1031.             BYTE *tmp = (BYTE *)GlobalLock(hImg);
  1032.             if (tmp!=NULL) {
  1033.                                        
  1034.                 // copy to our global RGB buffer, if we can
  1035.  
  1036.                 DWORD imgSize = w * h * 3;
  1037.  
  1038.                 CleanUp();
  1039.  
  1040.                 try {
  1041.                     m_rgbBuf = (BYTE *) new BYTE[imgSize];
  1042.                 } catch (CMemoryException *e) {
  1043.                     e->ReportError();
  1044.                     e->Delete();
  1045.                     CleanUp();
  1046.                     AfxGetApp()->DoWaitCursor(-1);
  1047.                     return;
  1048.                 }
  1049.  
  1050.                 // copy
  1051.                 memcpy(m_rgbBuf, tmp, imgSize);
  1052.                 m_width=w;
  1053.                 m_height=h;
  1054.  
  1055.                 // clean up
  1056.                 GlobalUnlock(hImg);
  1057.                 GlobalFree(hImg);
  1058.  
  1059.                 // redraw
  1060.                 InvalidateBeforeImage();
  1061.                 InvalidateAfterImage();
  1062.             }
  1063.         } else {
  1064.             AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1065.         }
  1066.  
  1067.         AfxGetApp()->DoWaitCursor(-1);
  1068.     }            
  1069. }
  1070.  
  1071.  
  1072. void CImgDlg::OnSave() 
  1073. {
  1074.     CString fileName;
  1075.     CString filt="JPG File (*.JPG)|*.JPG|24-Bit PNG File (*.PNG)|*.PNG|8-bit PNG File (*.PNG)|*.PNG|24-bit BMP (*.BMP)|*.BMP|8-bit BMP (*.BMP)|*.BMP|4-bit BMP (*.BMP)|*.BMP||";
  1076.     
  1077.     // OPENFILENAME - so i can get to its Help page easily
  1078.     CFileDialog fileDlg(FALSE,"*.JPG","*.JPG",NULL,filt,this);
  1079.  
  1080.     fileDlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
  1081.     fileDlg.m_ofn.lpstrTitle="File to save as";
  1082.  
  1083.     if (fileDlg.DoModal()==IDOK) {
  1084.         
  1085.         AfxGetApp()->DoWaitCursor(1);
  1086.  
  1087.         fileName=fileDlg.GetPathName();
  1088.         CString ext=fileName.Right(4);
  1089.  
  1090.         // draw the output image
  1091.         BYTE *tmp = RenderImage();
  1092.  
  1093.         DWORD imgByteSize = (m_width * m_height * 3);
  1094.  
  1095.         switch (fileDlg.m_ofn.nFilterIndex) {
  1096.         default:
  1097.         case 1: //JPG
  1098.             {
  1099.                 if (!ImgDLLSaveRGBToJPG(fileName, tmp, m_width, m_height, 75, TRUE)) {
  1100.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1101.                 }
  1102.             }
  1103.             break;
  1104.         case 2:    // PNG-24
  1105.             {
  1106.                 if (!ImgDLLSaveRGB24ToPNGRGB(fileName, tmp, m_width, m_height, 0.0)) {
  1107.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1108.                 }
  1109.             }
  1110.             break;
  1111.         case 3:    //    PNG-8
  1112.             {
  1113.                 int colors = (fileDlg.m_ofn.nFilterIndex == 5 ? 16 : 256);
  1114.  
  1115.                 // make a buffer for the quantized version
  1116.                 BYTE *qImg;
  1117.                 try {
  1118.                     qImg = (BYTE *) new BYTE[imgByteSize];
  1119.                 } catch (CMemoryException *e) {
  1120.                     e->ReportError();
  1121.                     e->Delete();
  1122.                     AfxGetApp()->DoWaitCursor(-1);
  1123.                     AfxMessageBox(StringFromErrorNum(MEMERR));
  1124.                     return ;
  1125.                 }
  1126.  
  1127.                 // quantize it
  1128.                 RGBQUAD pal[256];
  1129.                 if (!ImgDLLQuantizeRGBTo8Bit(tmp,
  1130.                                             qImg,
  1131.                                             m_width,
  1132.                                             m_height,
  1133.                                             colors,
  1134.                                             pal)) {
  1135.                     AfxGetApp()->DoWaitCursor(-1);
  1136.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1137.                     return;
  1138.                 }
  1139.  
  1140.                 // save it
  1141.                 if (!ImgDLLSave8BitToPNG8Bit(fileName,
  1142.                                                 qImg,
  1143.                                                 m_width,
  1144.                                                 m_height,
  1145.                                                 colors,
  1146.                                                 pal,
  1147.                                                 0.0)) {
  1148.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1149.                 }
  1150.                 delete [] qImg;
  1151.             }
  1152.             break;
  1153.  
  1154.         case 4: //24 bit BMP
  1155.             if (!ImgDLLSaveRGBToBMP24(fileName, tmp, m_width, m_height)) 
  1156.                 AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1157.  
  1158.             break;
  1159.  
  1160.         case 5: // 8-bit BMP, 4-bit BMP
  1161.         case 6:
  1162.             {
  1163.                 int colors = (fileDlg.m_ofn.nFilterIndex == 5 ? 16 : 256);
  1164.                 int bits = (fileDlg.m_ofn.nFilterIndex == 5 ? 4 : 8);
  1165.  
  1166.                 // make a buffer for the quantized version
  1167.                 BYTE *qImg;
  1168.                 try {
  1169.                     qImg = (BYTE *) new BYTE[imgByteSize];
  1170.                 } catch (CMemoryException *e) {
  1171.                     e->ReportError();
  1172.                     e->Delete();
  1173.                     AfxGetApp()->DoWaitCursor(-1);
  1174.                     AfxMessageBox(StringFromErrorNum(MEMERR));
  1175.                     return ;
  1176.                 }
  1177.  
  1178.                 // quantize it
  1179.                 RGBQUAD pal[256];
  1180.                 if (!ImgDLLQuantizeRGBTo8Bit(tmp,
  1181.                                             qImg,
  1182.                                             m_width,
  1183.                                             m_height,
  1184.                                             colors,
  1185.                                             pal)) {
  1186.                     AfxGetApp()->DoWaitCursor(-1);
  1187.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1188.                     return;
  1189.                 }
  1190.  
  1191.                 // save it
  1192.                 if (!ImgDLLSaveColormappedToBMP(fileName,
  1193.                                                 qImg,
  1194.                                                 m_width,
  1195.                                                 m_height,
  1196.                                                 bits,
  1197.                                                 colors,
  1198.                                                 pal)) {
  1199.                     AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1200.                 }
  1201.                 delete [] qImg;
  1202.             }
  1203.             break;
  1204.         }
  1205.         
  1206.         delete [] tmp;
  1207.  
  1208.         AfxGetApp()->DoWaitCursor(-1);
  1209.     }
  1210. }
  1211.  
  1212. ////////////////////////////////////////////////////////////////////////
  1213. //    this is where we apply the mod's
  1214.  
  1215. BYTE * CImgDlg::RenderImage()
  1216. {
  1217.     AfxGetApp()->DoWaitCursor(1);
  1218.  
  1219.     // copy it to our buffer
  1220.     DWORD imgByteSize = (m_width * m_height * 3);
  1221.  
  1222.     BYTE * outBuf;
  1223.     // alloc our buffer
  1224.     try {
  1225.         outBuf = (BYTE *) new BYTE[imgByteSize];
  1226.     } catch (CMemoryException *e) {
  1227.         e->ReportError();
  1228.         e->Delete();
  1229.         AfxGetApp()->DoWaitCursor(-1);
  1230.         CleanUp();
  1231.         return NULL;
  1232.     }
  1233.   
  1234.     // copy
  1235.     memcpy(outBuf, m_rgbBuf, imgByteSize);
  1236.  
  1237.     // grayscale
  1238.     if (m_doGray) {
  1239.         if (!ImgDLLMakeGrayScale(outBuf, m_width, m_height)) {
  1240.             AfxGetApp()->DoWaitCursor(-1);
  1241.             return outBuf;
  1242.         }
  1243.     }
  1244.  
  1245.     // flip
  1246.     if (m_doFlip) {
  1247.         if (!ImgDLLVerticalFlipBuf(outBuf, m_width * 3, m_height)) {
  1248.             AfxGetApp()->DoWaitCursor(-1);
  1249.             return outBuf;
  1250.         }
  1251.     }
  1252.  
  1253.     // RGB / BGR
  1254.     if (m_doRGBBGR) {
  1255.         if (!ImgDLLBGRFromRGB(outBuf, m_width, m_height)) {
  1256.             AfxGetApp()->DoWaitCursor(-1);
  1257.             return outBuf;
  1258.         }
  1259.     }
  1260.  
  1261.     // horiz flip
  1262.     if (m_doHFlip) {
  1263.         if (!ImgDLLHorizontalFlipRGB(outBuf, m_width, m_height)) {
  1264.             AfxGetApp()->DoWaitCursor(-1);
  1265.             return outBuf;
  1266.         }
  1267.     }
  1268.  
  1269.     // LUT
  1270.     if (m_doLUT) {
  1271.         if (!ImgDLLApplyLUTToRGB(outBuf, m_width, m_height, m_LUTChannelMask, m_LUT)) {
  1272.             AfxGetApp()->DoWaitCursor(-1);
  1273.             return outBuf;
  1274.         }
  1275.     }
  1276.  
  1277.     // histogram EQ
  1278.     if (m_doEQ) {
  1279.         if (!ImgDLLHistogramEqualizeRGB(outBuf, m_width, m_height, m_iEQLowLevel, m_iEQHighLevel, m_EQChannelMask)) {
  1280.             AfxGetApp()->DoWaitCursor(-1);
  1281.             return outBuf;
  1282.         }
  1283.     }
  1284.  
  1285.     // quantize
  1286.     if (m_doQuantize) {
  1287.         BYTE *tmp;
  1288.         try {
  1289.             tmp = (BYTE *) new BYTE[imgByteSize];
  1290.         } catch (CMemoryException *e) {
  1291.             e->ReportError();
  1292.             e->Delete();
  1293.             AfxGetApp()->DoWaitCursor(-1);
  1294.             return outBuf;
  1295.         }
  1296.  
  1297.         // quantize it
  1298.         RGBQUAD pal[256];
  1299.         if (!ImgDLLQuantizeRGBTo8Bit(outBuf,
  1300.                                     tmp,
  1301.                                     m_width,
  1302.                                     m_height,
  1303.                                     m_iQuantColors,
  1304.                                     pal)) {
  1305.             AfxGetApp()->DoWaitCursor(-1);
  1306.             return outBuf;
  1307.         } 
  1308.  
  1309.         // we really want a 24-bit image for display, so create a 24-bit image,
  1310.         // using the palette and the 8-bit image
  1311.         if (!ImgDLLRGBFrom8Bit(tmp,
  1312.                                 outBuf,
  1313.                                 m_width,
  1314.                                 m_height,
  1315.                                 m_iQuantColors,
  1316.                                 pal)) {
  1317.             AfxGetApp()->DoWaitCursor(-1);
  1318.             return outBuf;
  1319.         }
  1320.  
  1321.         delete [] tmp;
  1322.     }
  1323.  
  1324.     // matrix
  1325.     if (m_doMatrix) {
  1326.         BYTE *tmp;
  1327.         try {
  1328.             tmp = (BYTE *) new BYTE[imgByteSize];
  1329.         } catch (CMemoryException *e) {
  1330.             e->ReportError();
  1331.             e->Delete();
  1332.             AfxGetApp()->DoWaitCursor(-1);
  1333.             return outBuf;
  1334.         }
  1335.         if (!ImgDLLApplyMatrixToRGB(outBuf,    tmp, m_width, m_height,
  1336.                                     m_MatrixChannelMask, m_bZero, m_bFeedback, m_fMatrixLevel, m_fMatrix)) {
  1337.             AfxGetApp()->DoWaitCursor(-1);
  1338.             return outBuf;
  1339.         }
  1340.         memcpy(outBuf, tmp, imgByteSize);
  1341.         delete [] tmp;
  1342.     }
  1343.  
  1344.  
  1345.     // quick rotate
  1346.     if (m_quickRotationType!=-1) {
  1347.         ImgDLLQuickRotateRGB(outBuf, m_width, m_height, m_quickRotationType);
  1348.         // rotate 90 or 270, swap width and height
  1349.         if ((m_quickRotationType==0) || (m_quickRotationType==2)) {
  1350.             UINT t = m_width;
  1351.             m_width = m_height;
  1352.             m_height = t;
  1353.         }
  1354.     }
  1355.  
  1356.     // sharpen
  1357.     if (m_doSharpen) {
  1358.         BYTE *tmp;
  1359.         try {
  1360.             tmp = (BYTE *) new BYTE[imgByteSize];
  1361.         } catch (CMemoryException *e) {
  1362.             e->ReportError();
  1363.             e->Delete();
  1364.             AfxGetApp()->DoWaitCursor(-1);
  1365.             return outBuf;
  1366.         }
  1367.         if (!ImgDLLSharpenRGB(outBuf, tmp, m_width, m_height, m_iSharpenLevel)) {
  1368.             AfxGetApp()->DoWaitCursor(-1);
  1369.             return outBuf;
  1370.         }
  1371.         memcpy(outBuf, tmp, imgByteSize);
  1372.         delete [] tmp;
  1373.     }
  1374.  
  1375.  
  1376.     // blur
  1377.     if (m_doBlur) {
  1378.         BYTE *tmp;
  1379.         try {
  1380.             tmp = (BYTE *) new BYTE[imgByteSize];
  1381.         } catch (CMemoryException *e) {
  1382.             e->ReportError();
  1383.             e->Delete();
  1384.             AfxGetApp()->DoWaitCursor(-1);
  1385.             return outBuf;
  1386.         }
  1387.         if (!ImgDLLBlurRGB(outBuf, tmp, m_width, m_height, m_iBlurLevel)) {
  1388.             AfxGetApp()->DoWaitCursor(-1);
  1389.             return outBuf;
  1390.         }
  1391.         memcpy(outBuf, tmp, imgByteSize);
  1392.         delete [] tmp;
  1393.     }
  1394.  
  1395.     // count the colors
  1396.     UINT cols = ImgDLLCountRGBColors(outBuf, m_width, m_height, FALSE);
  1397.     CString t;
  1398.     t.Format("%u colors", cols);
  1399.     m_colorTextWnd.SetWindowText(t);
  1400.  
  1401.     if (m_EQGraphMask==0) {
  1402.         if (!ImgDLLGetBrightnessHistogram(outBuf,
  1403.                                 m_width,
  1404.                                 m_height,
  1405.                                 m_EQHisto)) {
  1406.         }
  1407.     } else {
  1408.         if (!ImgDLLGetChannelHistogram(outBuf,
  1409.                                 m_width,
  1410.                                 m_height,
  1411.                                 m_EQGraphMask,
  1412.                                 m_EQHisto)) {
  1413.         }
  1414.     }
  1415.  
  1416.     AfxGetApp()->DoWaitCursor(-1);
  1417.  
  1418.     return outBuf;
  1419. }
  1420.  
  1421.  
  1422. ////////////////////////////////////////////////////////////////////////
  1423.  
  1424. void CImgDlg::CleanUp()
  1425. {
  1426.     if (m_rgbBuf!=NULL) {
  1427.         delete [] m_rgbBuf;
  1428.         m_rgbBuf=NULL;
  1429.         m_width=m_height=0;
  1430.     }
  1431. }
  1432.  
  1433. ////////////////////////////////////////////////////////////////////////
  1434.  
  1435. void CImgDlg::LoadDefaultImage()
  1436. {
  1437.     CleanUp();
  1438.  
  1439.     // we'll need our palette to render the bitmap on < 16 bit displays
  1440.     HPALETTE hPal = (HPALETTE)m_pal.GetSafeHandle();
  1441.  
  1442.  
  1443.     //    use ImgDLLLoadResourceBMP, instead of CBitmap::LoadBitmap!
  1444.     //
  1445.     //    on 8-bit displays, LoadBitmap maps the bitmap to the 16-colors
  1446.     //    of the standard Windows palette - this is no good. you don't even
  1447.     //    get a chance to use a palette on the image because LoadBitmap mangles
  1448.     //    the color info!! yuck!!
  1449.     //
  1450.     //    if you use this function, with a palette that represents a
  1451.     //  spread of colors from the image, or even just a nice spread of
  1452.     //    colors all across the spectrum, you'll get much better results.
  1453.     //    trust me. 
  1454.     //    
  1455.     //    if you use a NULL palette, this function will use a 
  1456.     //    set of colors from the system palette, which will give slightly
  1457.     //    better results than LoadBitmap.
  1458.     //
  1459.     //    if you don't believe me, get into 256-color mode, replace the 
  1460.     //    ImgDLLLoadResourceBMP call with these two lines and see what happens.
  1461.     //
  1462.     //    CBitmap tmpBmp; tmpBmp.LoadBitmap(IDB_SAMPLE_IMAGE);
  1463.     //    HBITMAP hTmpBmp = tmpBmp.GetSafeHandle();
  1464.     //
  1465.  
  1466.     HBITMAP hTmpBmp = ImgDLLLoadResourceBMP(AfxGetInstanceHandle(),
  1467.                                             (LPSTR)IDB_SAMPLE_IMAGE,
  1468.                                             hPal);
  1469.  
  1470.     if (hTmpBmp==NULL) {
  1471.         AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1472.         return;
  1473.     }
  1474.  
  1475.     // get an RGB buffer from our HBITMAP, use the palette to render the bitmap
  1476.     HGLOBAL hImg = ImgDLLHBITMAPToRGB(hTmpBmp, 
  1477.                               &m_width, 
  1478.                               &m_height,
  1479.                               (HPALETTE)m_pal.GetSafeHandle());
  1480.  
  1481.     // clean up - me have the RGB buffer, we don't need the HBITMAP anymore
  1482.     ::DeleteObject(hTmpBmp);
  1483.  
  1484.     if (hImg!=NULL) {
  1485.  
  1486.         BYTE *pImg = (BYTE *)GlobalLock(hImg);
  1487.  
  1488.         if (pImg!=NULL) {
  1489.  
  1490.             // copy it to our buffer
  1491.             DWORD imgByteSize = (m_width * m_height * 3);
  1492.             
  1493.             // alloc our buffer
  1494.             try {
  1495.                 m_rgbBuf = (BYTE *) new BYTE[imgByteSize];
  1496.             } catch (CMemoryException *e) {
  1497.                 e->ReportError();
  1498.                 e->Delete();
  1499.                 CleanUp();
  1500.             }
  1501.  
  1502.             // copy
  1503.             memcpy(m_rgbBuf, pImg, imgByteSize);
  1504.  
  1505.             InvalidateBeforeImage();
  1506.             InvalidateAfterImage();
  1507.  
  1508.             GlobalUnlock(hImg);
  1509.         } else {
  1510.             AfxMessageBox("Failed to lock ptr");
  1511.             CleanUp();
  1512.         }
  1513.         GlobalFree(hImg);
  1514.     } else {
  1515.         AfxMessageBox(StringFromErrorNum(ImgDLLGetLastError()));
  1516.         return;
  1517.     }
  1518. }
  1519.  
  1520. ////////////////////////////////////////////////////////////////////////
  1521.  
  1522. CString CImgDlg::StringFromErrorNum(int err)
  1523. {
  1524.     CString out;
  1525.     out.Format("Error #%d", err);
  1526.  
  1527.     switch (err) {
  1528.     default             :        
  1529.         break;
  1530.     case IMGOK            :        out="No error"; 
  1531.         break;
  1532.     case NOGIFERR        :        out="No GIF support.."; 
  1533.         break;
  1534.     case CALLBACKCANCEL :        out="Operation cancelled by callback";
  1535.         break;
  1536.     case PNGCREATEERR    :        out="Internal PNG creation error - possibly bad params";
  1537.         break;    
  1538.     case IMGDLLINTERNAL :        out="Internal ImgDLL error";
  1539.         break;
  1540.     case IMGFONTERR        :        out="Font creation error";
  1541.         break;
  1542.     case MEMERR            :        out="Error : out of memory";
  1543.         break;
  1544.     case FILEOPENERR    :        out="Error on file open";
  1545.         break;
  1546.     case FILEREADERR    :        out="Error on file read";
  1547.         break;
  1548.     case FILEWRITEERR    :        out="Error on file write";
  1549.         break;
  1550.     case BADPARAMERR    :        out="Bad user param";
  1551.         break;
  1552.     case INVALIDBMPERR    :        out="Bad BMP file";
  1553.         break;
  1554.     case BMPRLEERR        :        out="We don't do RLE BMP files";
  1555.         break;
  1556.     case INVALIDGIFERR    :        out="Bad GIF file";
  1557.         break;
  1558.     case INVALIDTIFFERR    :        out="Bad TIF file";
  1559.         break;
  1560.     case INVALIDJPGERR    :        out="Bad jpg file";
  1561.         break;
  1562.     case TRIALVERSION    :        out = "DLL unlocked to Trial level functionality only";
  1563.         break;
  1564.     case IMGDCERR        :        out = "Device error";
  1565.         break;
  1566.     case IMGDIBERR        :        out = "GetDIBits error";
  1567.         break;
  1568.     case IMGNORESOURCE    :        out = "Resource Not Found";
  1569.         break;
  1570.     }
  1571.  
  1572.     return out;
  1573. }
  1574.  
  1575.  
  1576. void CImgDlg::OnAbout() 
  1577. {
  1578.     CAboutDlg dlgAbout;
  1579.     dlgAbout.DoModal();
  1580. }
  1581.  
  1582.  
  1583. // creates a spread of colors - no real method, just a semi-even spread
  1584. // this is all you really need to get better than Windows standard...
  1585. void CImgDlg::MakePalette()
  1586.     LPLOGPALETTE     lpPal;
  1587.     BYTE *           pLogPal;
  1588.     HPALETTE         hPal = NULL;
  1589.     int              i;
  1590.  
  1591.     try {
  1592.         pLogPal = new BYTE [sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (256))];
  1593.     } catch (CMemoryException *e) {
  1594.         e->ReportError();
  1595.         e->Delete();
  1596.         pLogPal==NULL;
  1597.         return;
  1598.     }
  1599.  
  1600.     lpPal = (LPLOGPALETTE) pLogPal;
  1601.     lpPal->palVersion = 0x300;
  1602.     lpPal->palNumEntries = 256;
  1603.  
  1604.     int r,g,b;
  1605.     r=b=g=0;
  1606.     for (i=0;i<256;i++) {
  1607.         lpPal->palPalEntry[i].peRed   = r % 256;
  1608.         lpPal->palPalEntry[i].peGreen = g % 256;
  1609.         lpPal->palPalEntry[i].peBlue  = b % 256;
  1610.         lpPal->palPalEntry[i].peFlags = 0;
  1611.  
  1612.        r+=16;
  1613.        g+=4;
  1614.        b++;
  1615.     }
  1616.  
  1617.     BOOL ok = m_pal.CreatePalette (lpPal);
  1618.  
  1619.     delete [] pLogPal;
  1620. }
  1621.  
  1622.